﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NetJsWire.Lite.Widgets.UI;
using Newtonsoft.Json;

namespace NetJsWire.Lite.Widgets
{
    /// A generic custom type descriptor for the specified type  
    /// </summary>  
    public sealed class BaseComponentTypeDescriptionProvider : TypeDescriptionProvider
    {
        /// <summary>  
        /// Constructor  
        /// </summary>  
        public BaseComponentTypeDescriptionProvider( TypeDescriptionProvider parent )
            : base( parent )
        {
        }

        /// <summary>  
        /// Create and return a custom type descriptor and chains it with the original  
        /// custom type descriptor  
        /// </summary>  
        public override ICustomTypeDescriptor GetTypeDescriptor( Type objectType, object instance )
        {
            return new BaseComponentCustomTypeDescriptor( base.GetTypeDescriptor( objectType, instance ), instance );
        }
    }

    /// <summary>  
    /// A custom type descriptor which attaches a <see cref="SecuredAttribute"/> to   
    /// an instance of a type which implements <see cref="ISecurable"/>  
    /// </summary>  
    public sealed class BaseComponentCustomTypeDescriptor : CustomTypeDescriptor
    {
        private BaseComponent _component;
        /// <summary>  
        /// Constructor  
        /// </summary>  
        public BaseComponentCustomTypeDescriptor( ICustomTypeDescriptor parent )
            : base( parent )
        {

        }

        /// <summary>  
        /// Constructor  
        /// </summary>  
        public BaseComponentCustomTypeDescriptor( ICustomTypeDescriptor parent, object instance )
            : base( parent )
        {
            _component = instance as BaseComponent;
        }

        //public override AttributeCollection GetAttributes()
        //{
        //    Type baseComponentType = typeof( T ).GetInterface( typeof( IBaseComponent ).Name );
        //    if ( baseComponentType != null )
        //    {
        //        IBaseComponent securableInstance = GetPropertyOwner( base.GetProperties().Cast<PropertyDescriptor>().First() ) as IBaseComponent;
        //        string[] instanceLevelRoles = securableInstance.GetRoles();
        //        List<Attribute> attributes = new List<Attribute>( base.GetAttributes().Cast<Attribute>() );
        //        SecuredAttribute securedAttrib = new SecuredAttribute( instanceLevelRoles );
        //        TypeDescriptor.AddAttributes( securableInstance, securedAttrib );
        //        attributes.Add( securedAttrib );
        //        return new AttributeCollection( attributes.ToArray() );
        //    }
        //    return base.GetAttributes();

        //}
        /// <summary>  
        /// This method add a new property to the original collection  
        /// </summary>  
        public override PropertyDescriptorCollection GetProperties()
        {
            return GetProperties( new Attribute[ 0 ] );
        }

        public override PropertyDescriptorCollection GetProperties( Attribute[] attributes )
        {
            PropertyDescriptorCollection originalProperties = base.GetProperties( attributes );
            List<PropertyDescriptor> newProperties = new List<PropertyDescriptor>();

            if ( _component != null && _component.ShouldSerializeExtraProperties() )
            {
                newProperties.AddRange( originalProperties.Cast<PropertyDescriptor>() );
                foreach ( var property in _component.ExtraProperties )
                {
                    Attribute[] attrs = new Attribute[] { new JsonPropertyAttribute( property.Name ), BrowsableAttribute.Yes };
                    var pd = TypeDescriptor.CreateProperty( _component.GetType(), property.Name, typeof( string ), attrs );
                    pd.SetValue( _component, property.Value );
                    newProperties.Add( pd );
                }

                return new PropertyDescriptorCollection( newProperties.ToArray(), true ); ;
            }

            return originalProperties;
        }
    }
}
